#include "clib_main.h"
#include "clib_type.h"
#include "clib_core.h"
#include "net/clib_stack.h"
#include "net/clib_stack_netif.h"
#include "net/clib_stack_malloc.h"
#include "net/clib_dpdk_packet.h"
#include "inc/clib_config.h"
#include <rte_ip.h>
#include <rte_ethdev.h>
#include <rte_mempool.h>
#include "clib_conf_field.h"
#include "clib_cycle.h"
#include "clib_dpdk_port.h"

i32_t cnet_worker_loop(void* arg);

i32_t clib_env_init(char* program);

i32_t main(i32_t argc, char *argv[])
{
 
    /** TODO 参数解析 **/
    if(clib_option_pars(argc, argv) < 0) {
        return -1;
    }

    /** TODO 加载配置文件 **/
    if(clib_load_conf(clib_conf_name) < 0) {
        return -1;
    }

    /** TODO 设置日志文件 **/
    if(clib_log_init(clib_core_load.log, clib_core_load.log_type, clib_core_load.log_level) < 0) {
        return -1;
    }

    /** TODO 解析配置选项 **/

    if(clib_env_init(argv[0]) < 0) {
        return -1;
    }
    /** TODO 初始化环境  **/
        //1、运行环境
        //2、网卡
        //3、
        //4、
        //5、
    
    /** TODO 加载配置 **/
    if(clib_load_cycle(&clib_core_load) < 0) {
        return -1;
    }

    if(clib_netif_init(&clib_cycle_conf) < 0) {
        return -1;
    }

    

    /** TODO 加载线程模型 **/
    /** TODO master线程 **/

    /** TODO 清理环境 **/

    return 0;
}

i32_t cnet_worker_loop(void* arg)
{
    int16_t              queue = 0;
    uint64_t             prev_dtsc;
    uint64_t             cur_dtsc;  
    uint64_t             diff_dtsc;
    uint64_t             tick_dtsc;
    //cnet_handle_t       *handles;
    i32_t                handle_n;
    //cnet_handle_t       *handle;
    uint16_t             nb_rx = 64;
    uint16_t             lcore_id  = rte_lcore_id();
    int16_t              socket_id = rte_socket_id();
    uint16_t             port_id   = 0;
    clib_stack_t         *stack = &l4_satck;
    stack_netif_t        *netif = clib_stack_malloc("",sizeof(stack_netif_t), 64, socket_id);
    struct rte_mempool*  pool;
    netif->ipv4  =  RTE_IPV4(192,168,0,88);
    netif->ipv4_mask =  RTE_IPV4(255,255,255,0);
    netif->core_id = lcore_id;
    netif->ipv4_prefix = 24;
    netif->args = pool;
    netif->opts = &dpdk_pkt_opt;     
    stack->ctx[queue].netif[port_id] = netif;

    
    return rn_ok;
}


i32_t clib_env_init(char* program)
{
    /** TODO其他 **/
    i08_t cache[256];

    clib_core_conf_t   *core;

    core  = &clib_core_load;
   
    strcpy(dpdk_argv[dpdk_argc++], program);
   
    /** 组装pci**/
    for(i32_t i = 0; i < core->dpdk_dev_cnt; i++) {
        strcpy(dpdk_argv[dpdk_argc++], "-a");
        strcpy(dpdk_argv[dpdk_argc++], core->dpdk_dev[i].pci);
    }

    strcpy(dpdk_argv[dpdk_argc],"--lcores=");
    for(i32_t i = 0; i < core->cpu_cnt; i++) {
        if(i == 0) {
            sprintf(cache,"%d@(%d)", i,core->cpu[i]);
            strcat(dpdk_argv[dpdk_argc], cache);
        }else {
            sprintf(cache,",%d@(%d)", i,core->cpu[i]);
            strcat(dpdk_argv[dpdk_argc], cache);
        }  
    }
    dpdk_argc++;

    strcpy(dpdk_argv[dpdk_argc++], "-n4");

    strcpy(dpdk_argv[dpdk_argc++], "--proc-type=auto");
    
    sprintf(cache,"--file-prefix=%s",core->prefix);

    strcpy(dpdk_argv[dpdk_argc++], cache);

    //strcpy(dpdk_argv[dpdk_argc++], "--log-level=debug");
    if(rte_eal_init(dpdk_argc,dpdk_argv) < 0) {
        tnet_log_error("dpdk eal init error \n");
        return rn_error;
    }

    return 0;
}


int32_t clib_option_pars(int32_t argc,char** argv)
{
    i32_t opt = 0;
    i32_t idx = 0;

    if(argc == 1)
    {
        tnet_option_help();
        return -1;
    }

    while ((opt = getopt_long_only(argc, argv, clib_option_short, clib_option_long, &idx)) != -1)
    {
        switch (opt)
        {
        case 'h':
            clib_option_help();
            return -1;
            break;
        case 'v':
            return -1;
            break;
        case 's':
            /* TODO */
            break;
        case 'c':
            clib_conf_name = optarg;
            break;
        case 'l':
            clib_log_name = optarg;
            break;        
        default:
            break;
        }
    }

    return rn_ok;
}

/**
 * 程序参数打印
 */
void clib_option_help()
{
    printf("[usage: clib program options]       \n");
    printf("-h --help       show program help   \n");
    printf("-v --version    show program version\n");
    printf("-s --show       Show module conf    \n");
    printf("-c --conf       Run with conf file  \n");
    printf("-l --log        log file path       \n"); 
}

/**
 *    加载配置文件
 * 
 * @param cfg 配置文件
 * @return 
 *   0  成功
 *   -1 失败
 */
i32_t clib_load_conf(const char* cfg)
{
    if(!cfg) {
        return -1;
    }

    clib_config_init(&clib_conf_load);

    if(clib_config_read(&clib_conf_load, cfg) < 0) {
        return -1;
    }

    memset(&clib_core_load, 0, sizeof(clib_core_conf_t));

    return clib_conf_pars_core(&clib_conf_load, &clib_core_load); 
}

/**
 * @brief: 解析 tnet_conf_t 中的 core 配置项
 * @param tnet_conf 结构体指针
 * @param tnet_core 结构体指针
 * @return 返回解析结果，成功返回 rn_ok
 */
i32_t clib_conf_pars_core(clib_config_t* conf,clib_core_conf_t *clib_core) 
{
    /** TODO 解析其他配置函数添加 **/
    clib_config_t      *entry;           // 配置项指针
    clib_config_t      *entrys[128];     // 配置项数组
    i32_t               entry_cnt;       // 配置项数量
    clib_conf_t         argv;    

    if(!conf || !clib_core) { // 如果 tnet_conf 或 tnet_core 为空，则返回错误
        return rn_error;
    }
    clib_core->conf = conf;
    // argv 数组
    // 获取 core 配置项的数量和信息
    entry = clib_config_find_child(conf, "core");

    while(entry) {
        /** TODO **/
        if(!strcmp(entry->key,"log")) {
            strcpy(clib_core->log, entry->value.ptr);
        } else if(!strcmp(entry->key,"cpu")) {
            clib_core->cpu_cnt = clib_filed_arrary_string(entry,1,(void**)clib_core->cpu);
        } else if(!strcmp(entry->key,"listen")) {
            clib_core->listen = atoi(entry->value.ptr);
        } else if(!strcmp(entry->key,"prefix")) {
            strcpy(clib_core->prefix, entry->value.ptr);
        }

        entry = entry->next;
    }

    entry = clib_config_find_child(conf, "dpdk");
    if(entry) {
        entry_cnt = clib_config_all_child(entry, entrys);
        clib_core->dpdk_dev_cnt = entry_cnt;
        for(i32_t i =0; i < entry_cnt; i++) {
            entry = clib_config_first_child(entrys[i]);
            while(entry) {
                if(!strcmp(entrys[i]->key, "name")) {
                    strcpy(clib_core->dpdk_dev[i].name, entry->value.ptr);
                } else if(!strcmp(entrys[i]->key, "pci")) {
                    strcpy(clib_core->dpdk_dev[i].pci, entry->value.ptr);
                } else if(!strcmp(entrys[i]->key, "rx_que")) {
                    clib_core->dpdk_dev[i].rx_queue = atoi(entry->value.ptr);
                } else if(!strcmp(entrys[i]->key, "tx_que")) {
                    clib_core->dpdk_dev[i].tx_queue = atoi(entry->value.ptr);
                } else if(!strcmp(entrys[i]->key, "tx_mbuf")) {

                } else if(!strcmp(entrys[i]->key, "rx_mbuf")) {

                }

                entry = entry->next;
            }
        }
    }
    
    return rn_ok;
}


i32_t clib_netif_init(clib_cycle_t *cycle)
{
    if(clib_dpdk_netif_init(cycle->netif, &cycle->port_conf) < 0) {
        return -1;
    }

    return 0;
}

i32_t clib_load_module(clib_cycle_t *cycle)
{

}

